package com.rickpan.repository;

import com.rickpan.entity.ShareAccessLog;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.repository.JpaRepository;
import org.springframework.data.jpa.repository.Query;
import org.springframework.data.repository.query.Param;
import org.springframework.stereotype.Repository;

import java.time.LocalDateTime;
import java.util.List;

/**
 * 分享访问记录Repository接口
 * 
 * @author RickPan Team
 * @since 2025-01-05
 */
@Repository
public interface ShareAccessLogRepository extends JpaRepository<ShareAccessLog, Long> {

    /**
     * 根据分享ID查找访问记录
     */
    Page<ShareAccessLog> findByShareId(Long shareId, Pageable pageable);

    /**
     * 根据分享ID和操作类型查找访问记录
     */
    List<ShareAccessLog> findByShareIdAndActionType(Long shareId, ShareAccessLog.ActionType actionType);

    /**
     * 统计分享的访问次数
     */
    long countByShareId(Long shareId);

    /**
     * 统计分享的成功访问次数
     */
    long countByShareIdAndSuccess(Long shareId, Boolean success);

    /**
     * 统计分享在指定时间范围内的访问次数
     */
    @Query("SELECT COUNT(sal) FROM ShareAccessLog sal " +
           "WHERE sal.shareId = :shareId " +
           "AND sal.accessTime >= :startTime " +
           "AND sal.accessTime <= :endTime " +
           "AND sal.success = true")
    long countByShareIdAndTimeRange(@Param("shareId") Long shareId,
                                   @Param("startTime") LocalDateTime startTime,
                                   @Param("endTime") LocalDateTime endTime);

    /**
     * 统计IP在指定时间范围内的访问次数 (用于频率限制)
     */
    @Query("SELECT COUNT(sal) FROM ShareAccessLog sal " +
           "WHERE sal.shareId = :shareId " +
           "AND sal.visitorIp = :ip " +
           "AND sal.accessTime >= :startTime")
    long countByShareIdAndIpAndTimeAfter(@Param("shareId") Long shareId,
                                        @Param("ip") String ip,
                                        @Param("startTime") LocalDateTime startTime);

    /**
     * 获取分享的最近访问记录
     */
    @Query("SELECT sal FROM ShareAccessLog sal " +
           "WHERE sal.shareId = :shareId " +
           "ORDER BY sal.accessTime DESC")
    Page<ShareAccessLog> findRecentAccessByShareId(@Param("shareId") Long shareId, Pageable pageable);

    /**
     * 获取用户所有分享的访问记录
     */
    @Query("SELECT sal FROM ShareAccessLog sal " +
           "JOIN FileShare fs ON sal.shareId = fs.id " +
           "WHERE fs.userId = :userId " +
           "ORDER BY sal.accessTime DESC")
    Page<ShareAccessLog> findByUserId(@Param("userId") Long userId, Pageable pageable);

    /**
     * 统计今日访问次数
     */
    @Query("SELECT COUNT(sal) FROM ShareAccessLog sal " +
           "WHERE sal.accessTime >= :startOfDay " +
           "AND sal.accessTime < :endOfDay " +
           "AND sal.success = true")
    long countTodayAccess(@Param("startOfDay") LocalDateTime startOfDay,
                         @Param("endOfDay") LocalDateTime endOfDay);

    /**
     * 获取访问统计数据 (按日期分组)
     */
    @Query("SELECT DATE(sal.accessTime) as accessDate, COUNT(sal) as accessCount " +
           "FROM ShareAccessLog sal " +
           "WHERE sal.shareId = :shareId " +
           "AND sal.accessTime >= :startTime " +
           "AND sal.success = true " +
           "GROUP BY DATE(sal.accessTime) " +
           "ORDER BY accessDate DESC")
    List<Object[]> getAccessStatsByDate(@Param("shareId") Long shareId,
                                       @Param("startTime") LocalDateTime startTime);

    /**
     * 删除指定时间之前的访问记录 (用于数据清理)
     */
    void deleteByAccessTimeBefore(LocalDateTime cutoffTime);

    /**
     * 删除分享的所有访问记录
     */
    void deleteByShareId(Long shareId);

    /**
     * 统计多个分享的总访问次数
     */
    long countByShareIdIn(List<Long> shareIds);

    /**
     * 统计多个分享在指定时间范围内的访问次数
     */
    long countByShareIdInAndAccessTimeBetween(List<Long> shareIds, LocalDateTime startTime, LocalDateTime endTime);

    /**
     * 统计多个分享指定操作类型的访问次数
     */
    long countByShareIdInAndActionType(List<Long> shareIds, ShareAccessLog.ActionType actionType);

    /**
     * 根据分享ID查询访问日志，按访问时间倒序
     */
    Page<ShareAccessLog> findByShareIdOrderByAccessTimeDesc(Long shareId, Pageable pageable);
}
